// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import NotFound from '@/views/NotFound'
import { resetRouter } from '../router'
import { getUserResourceTree, getDictAllModel } from '@/apis/user'
import { deepClone, removeToken } from '@/utils/tools'

// 此处的IS_TESTING就是用来判断当前是拉取数据库的真实菜单还是直接用前端的menu.json
const IS_TESTING = process.env.VUE_APP_USE_SQL === "false" ? true : false;

// import { Message } from 'element-ui'

Vue.use(Vuex)

// 生产可访问的路由表
const createRouter = (routes, cname = '') => {
  // array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
  return routes.reduce((prev, {
    type,
    uri: path,
    componentPath,
    name,
    title,
    icon,
    redirectUri: redirect,
    hidden,
    fullScreen,
    noCache,
    children = []
  }) => {
    // 是菜单项（MN）就注册到路由进去
    if (type === 'MN') {
      prev.push({
        path,
        // 此处就是webpack动态导入啦，是不是so easy，妈妈再也不用担心我再写一份routerMap放到源码里了
        component: () => import(`@/${componentPath}`),
        name: (cname + '-' + name).slice(1),
        props: true,
        redirect,
        meta: { title, icon, hidden: hidden === 'Y', type, fullScreen: fullScreen === 'Y', noCache: noCache === 'Y' },
        children: children.length ? createRouter(children, cname + '-' + name) : []
      })
    }
    return prev
  }, [])
}

// 生产权限按钮表(仅保存拼接的name)
const createPermissionBtns = router => {
  let btns = []
  const c = (router, name = '') => {
    router.forEach(v => {
      v.type === 'BT' && btns.push((name + '-' + v.name).slice(1))
      // return 不会结束forEach遍历，仅返回btns
      return v.children && v.children.length ? c(v.children, name + '-' + v.name) : null
    })
    return btns
  }
  return c(router)
}

export default new Vuex.Store({
  state: {
    collapse: false, // 菜单栏是否收缩
    authorized: false, // 是否拉取了授权菜单（不管来源）
    dict: {},
    accsessRoutes: [], // 已注册的路由
    permissionBtns: [], // 有权限的按钮
    navTags: [], // 标签导航列表
    cachedViews: [] // 缓存的页面
  },
  // 缓存效果
  getters: {
    collapse: state => state.collapse,
    cachedViews: state => state.cachedViews,
    accsessRoutes: state => state.accsessRoutes,
    // 菜单栏(过滤掉hidden为true的路由项)
    menuList: state => {
      const filterMenus = menus => {
        return menus.filter(item => {
          if (item.children && item.children.length) {
            item.children = filterMenus(item.children)
          }
          return item.meta && !item.meta.hidden
        })
      }
      return filterMenus(deepClone(state.accsessRoutes))
    },
    navTags: state => state.navTags
  },
  // 同步修改
  mutations: {
    // 修改已拉取标志和报存已注册的路由
    SET_ACCSESS_ROUTES(state, accsessRoutes) {
      state.authorized = true
      state.accsessRoutes = accsessRoutes
    },
    // 保存字典数据
    SET_ALL_DICT(state, dict) {
      state.dict = dict
    },
    // 保存btn权限
    SET_PERMISSION_BTNS(state, btns) {
      state.permissionBtns = btns
    },
    // 设置全局侧边栏展开、收起
    SET_COLLAPSE(state, flag) {
      state.collapse = flag
    },
    // 设置缓存页面（noCache字段）
    SET_CACHED_VIEWS(state, cachedViews) {
      state.cachedViews = cachedViews
    },
    // 退出登录
    LOGOUT: state => {
      state.cachedViews = []
      state.authorized = false
      resetRouter()
      // 删除cookie信息
      removeToken()
    }
  },
  actions: {
    // 异步获取路由信息
    setAccessRoutes: ({ commit }) => {
      return new Promise(async (resolve, reject) => {
        // 404页面选择在动态添加路由之后再注册进来，是因为如果开始就注册到项目中，在addRoutes之后会有限匹配该404，造成BUG
        const routerExt = [
          { path: '*', redirect: '/404' },
          { path: '/404', component: NotFound }
        ];

        // getUserResourceTree这个接口逻辑是查询当前登录人角色所包含的资源，过滤出模块名(这里是ADMIN)下面的子节点（包含菜单和按钮）
        const res = await (IS_TESTING ? import('@/router/menu.json') : getUserResourceTree('ADMIN'))
        if (!res) return reject()
        let router;// 当前系统路由信息
        if (IS_TESTING) {
          // IS_TESTING为true读取的是menu.json
          // 这里取第0个是因为我这个系统是属于大系统的第一个子系统
          router = res[0].children
        } else {
          if (!res.data.length) {
            reject()
            console.log('用户未配置菜单或菜单配置不正确，请检查后重试~')
            return
            // return Message.error('用户未配置菜单或菜单配置不正确，请检查后重试~')
          } else {
            router = res.data
          }
        }

        // 根据拉取数据整合成路由组并通过concat在尾部添加404
        const accessRoutes = createRouter(router).concat(routerExt)
        commit('SET_ACCSESS_ROUTES', accessRoutes)
        commit('SET_PERMISSION_BTNS', createPermissionBtns(router))
        resolve(accessRoutes)
      })
    },
    // 异步获取字典
    setAllDict: async ({ commit }) => {
      if (IS_TESTING) return
      const res = await getDictAllModel()
      if (!res) return
      commit('SET_ALL_DICT', res.data)
    },
    // 退出登录
    logout: ({ commit }) => {
      return new Promise(resolve => {
        commit('LOGOUT')
        resolve()
      })
    }
  }
})
